package com.example.android.utils.websocket

import android.util.Log
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleRegistry
import okhttp3.*
import okio.ByteString
import java.lang.Exception

class OkHttpWebSocket(url: String) {

    val WebSocketUrl = url
    var IsOpen = false
    var IsClosed = false
    private var _ConnectionMutex = false
    private lateinit var WebSocket: WebSocket
    lateinit var OnOpen: (response: Response) -> Unit
    lateinit var OnMessage: (bytes: ByteString) -> Unit
    lateinit var OnClosed: (code: Int, reason: String) -> Unit
    lateinit var OnFaliure: (t: Throwable, response: Response?) -> Unit



    fun Open() {
        // ...
        val httpClient = OkHttpClient.Builder()
            .pingInterval(40, java.util.concurrent.TimeUnit.SECONDS) // 设置 PING 帧发送间隔
            .build()
        val request = Request.Builder()
            .url(WebSocketUrl)
            .build()
        httpClient.newWebSocket(request, object : WebSocketListener() {
            override fun onOpen(webSocket: WebSocket, response: Response) {
                super.onOpen(webSocket, response)
                // WebSocket 连接建立
                this@OkHttpWebSocket.WebSocket = webSocket
                IsOpen = true
                _ConnectionMutex = true
                OnOpen(response)
            }


            override fun onMessage(webSocket: WebSocket, bytes: ByteString) {
                super.onMessage(this@OkHttpWebSocket.WebSocket, bytes)
                OnMessage(bytes)
            }

            override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
                super.onClosed(this@OkHttpWebSocket.WebSocket, code, reason)
                // WebSocket 连接关闭
                IsClosed = true
                _ConnectionMutex = false
                OnClosed(code, reason)
            }

            override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
                super.onFailure(webSocket, t, response)
                // 出错了
                webSocket.cancel()
                webSocket.close(1001, "Abnormal Closed")
                Thread.sleep(10000)
                Log.e(
                    toString(),
                    "Failed To Correspond With The Server \n Caused By $t : ${t.message} \n "
                )
                t.printStackTrace()

                _ConnectionMutex = false
                if (!IsOpen) Log.w(toString(), "Connection Has NOT Been Opened")
                if (IsClosed) Log.w(toString(), "Connection Had Been Closed")

                OnFaliure(t, response)
            }
        })
    }

    fun TryReconnect() : Boolean{
        if(!_ConnectionMutex){
            Open()
            return true
        }
        return false
    }

    fun Send(bytes: ByteString) {
        try {
            if (IsOpen && !IsClosed) {
                WebSocket.send(bytes)
            }
        } catch (e: Exception) {
            throw Exception("Failed To Send Message \n Caused By : ", e)
        }
    }

    fun Close() {
        if(this::WebSocket.isInitialized)
            WebSocket.close(1000, "Normal")
    }

}